// KCPTestServer project main.go
package main

import (
	"fmt"
	"net"
	"sync/atomic"
	"time"

	"github.com/xtaci/kcp-go"
)

const (
	SVR_PORT = ":5555"
)

var tcpCliCnt, kcpCliCnt, kcpRecvSize, tcpRecvSize uint64

func handleKCPEcho(conn *kcp.UDPSession) {

	conn.SetStreamMode(false)
	conn.SetWindowSize(4096, 4096)
	conn.SetNoDelay(1, 20, 2, 1)
	conn.SetDSCP(46)
	conn.SetMtu(1400)
	conn.SetACKNoDelay(true)
	conn.SetReadDeadline(time.Now().Add(time.Hour))
	conn.SetWriteDeadline(time.Now().Add(time.Hour))
	buf := make([]byte, 65536)
	for {
		n, err := conn.Read(buf)
		if err != nil {
			panic(err)
		}
		conn.Write(buf[:n])
		atomic.AddUint64(&kcpRecvSize, uint64(n))
	}
}

func kcpServer() {

	kcplistener, err := kcp.ListenWithOptions(SVR_PORT, nil, 10, 3)
	if err != nil {
		panic(err)
	}
	kcplistener.SetReadBuffer(4 * 1024 * 1024)
	kcplistener.SetWriteBuffer(4 * 1024 * 1024)
	kcplistener.SetDSCP(46)
	for {
		s, err := kcplistener.Accept()
		if err != nil {
			return
		}
		atomic.AddUint64(&kcpCliCnt, 1)
		// coverage test
		s.(*kcp.UDPSession).SetReadBuffer(4 * 1024 * 1024)
		s.(*kcp.UDPSession).SetWriteBuffer(4 * 1024 * 1024)
		go handleKCPEcho(s.(*kcp.UDPSession))
	}
}

func tcpServer() {
	lis, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), 5555, ""})
	if err != nil {
		panic(err)
	}

	for {
		conn, err := lis.AcceptTCP()
		if err != nil {
			panic(err)
		}
		atomic.AddUint64(&tcpCliCnt, 1)
		go func() {
			buf := make([]byte, 65536)
			for {
				n, err := conn.Read(buf)
				if err != nil {
					panic(err)
				}
				conn.Write(buf[:n])
				atomic.AddUint64(&tcpRecvSize, uint64(n))
			}
		}()
	}
}

func main() {
	fmt.Println("Hello World!")
	go kcpServer()
	go tcpServer()
	var (
		// 每10秒打印一次统计数据
		timeTicker = time.NewTicker(time.Second * 10)
	)

	for {
		select {
		case <-timeTicker.C:
			kcpSize := atomic.SwapUint64(&kcpRecvSize, 0)
			tcpSize := atomic.SwapUint64(&tcpRecvSize, 0)
			fmt.Println("KCP cnt:", kcpCliCnt, " recved size:", kcpSize, " tcp cnt", tcpCliCnt, " recved size:", tcpSize)

		}
	}
	fmt.Println("KCPTestServer is stoped!")
}
